package com.example.api.aspect;

import com.example.api.dao.OperateLogDao;
import com.example.api.model.entity.Admin;
import com.example.api.model.entity.OperateLog;
import com.example.api.model.enums.ActionTypeEnum;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Date;

@Aspect
@Component
public class SystemLogAspect {

    @Resource
    private OperateLogDao operateLogDao;

    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);
    public static Admin admin = new Admin();

    public static void getAdmin(Admin param) {
        admin = param;
    }

    // Controller层切点
    @Pointcut("execution(* com.example.api.controller..*.*(..))")
    public void controllerAspect() {}

    /**
     * 前置通知 用于拦截Controller层记录用户操作
     * @param joinPoint
     */
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {
        if (logger.isDebugEnabled()) {
            logger.info("before " + joinPoint);
        }
    }

    @After("controllerAspect()")
    public void after(JoinPoint joinPoint) {
        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodsName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class<?> targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            ActionTypeEnum logType = null;
            String logContent = "";
            for (Method method : methods) {
                if (method.getName().equals(methodsName)) {
                    Class<?>[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        logType = method.getAnnotation(SystemControllerLog.class).actionType();
                        logContent = method.getAnnotation(SystemControllerLog.class).description();
                        break;
                    }
                }
            }
            OperateLog operateLog = new OperateLog();
            operateLog.setType(logType.getMessage());
            operateLog.setContent(logContent);
            operateLog.setCode(HttpStatus.OK.toString());
            operateLog.setAid(admin.getId());
            operateLog.setCreateTime(new Date());
            operateLogDao.insertSelective(operateLog);
        } catch (Exception e) {
            logger.error("异常信息：{}", e.getMessage());
        }
    }

    /**
     * 配置后置返回通知，使用在方法aspect()上注册的切入点
     * @param joinPoint
     */
    @AfterReturning("controllerAspect()")
    public void afterReturn(JoinPoint joinPoint) {
        if (logger.isInfoEnabled()) {
            logger.info("afterReturn " + joinPoint);
        }
    }

    @AfterThrowing(pointcut = "controllerAspect()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodsName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class<?> targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            ActionTypeEnum logType = null;
            String logContent = "";
            for (Method method : methods) {
                if (method.getName().equals(methodsName)) {
                    Class<?>[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        logType = method.getAnnotation(SystemControllerLog.class).actionType();
                        logContent = method.getAnnotation(SystemControllerLog.class).description();
                        break;
                    }
                }
            }
            OperateLog operateLog = new OperateLog();
            operateLog.setType(logType.getMessage());
            operateLog.setContent(logContent);
            operateLog.setCode(e.getMessage());
            operateLog.setAid(admin.getId());
            operateLog.setCreateTime(new Date());
            operateLogDao.insertSelective(operateLog);
        } catch (Exception ex) {
            logger.error("异常信息：{}" + ex.getMessage());
        }
        logger.error("异常方法：{}异常代码：{}异常信息：{}参数：{}", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage());
    }

}
